package main

import (
	"encoding/xml"
	"fmt"
	"github.com/spf13/cobra"
	"iot/common"
	"iot/common/sys"
	"os"
	"time"
)

type FullImportXML struct {
	XMLName  xml.Name `xml:"root"`
	Protocol struct {
		Name        string `xml:"name,attr"`
		Description string `xml:"description,attr"`
		Type        int    `xml:"type,attr"`
		State       string `xml:"state,attr"`
	} `xml:"protocol"`
	Config struct {
		Name        string `xml:"name,attr"`
		Description string `xml:"description,attr"`
		Type        string `xml:"type,attr"` // tcp | serial

		// 以下是通用字段
		Timeout int `xml:"timeout,attr"`

		// TCP专有字段
		IP   string `xml:"ip,attr,omitempty"`
		Port int    `xml:"port,attr,omitempty"`

		// 串口专有字段
		SerialPort string `xml:"serial_port,attr,omitempty"`
		BaudRate   int    `xml:"baud_rate,attr,omitempty"`
		DataBits   int    `xml:"data_bits,attr,omitempty"`
		StopBits   int    `xml:"stop_bits,attr,omitempty"`
		Parity     string `xml:"parity,attr,omitempty"`
	} `xml:"config"`
	Groups []struct {
		index       string
		Name        string `xml:"name,attr"`
		Description string `xml:"description,attr"`
		Parameters  []struct {
			index            string
			Name             string `xml:"name,attr"`
			Description      string `xml:"description,attr"`
			DataType         string `xml:"dataType,attr"`
			ParamType        string `xml:"paramType,attr"`
			DefaultValue     string `xml:"defaultValue,attr"`
			TriggerType      string `xml:"triggerType,attr"`
			TriggerCondition string `xml:"triggerCondition,attr"`
			ByteOrder        string `xml:"byteOrder,attr"`
			HistoryStorage   string `xml:"historyStorage,attr"`
			Point            *struct {
				TypeStr  string  `xml:"type,attr"`
				SlaveID  int     `xml:"slave_id,attr"`
				Address  int     `xml:"address,attr"`
				Base     float64 `xml:"base,attr"`
				Coef     float64 `xml:"coef,attr"`
				Interval int     `xml:"interval,attr"`
				Priority int     `xml:"priority,attr"`
				Offset   int     `xml:"offset,attr"`
				Length   int     `xml:"length,attr"`
			} `xml:"point"`
			FollowParameters []struct {
				DevName string `xml:"dev_name,attr"`
				Group   string `xml:"group,attr"`
				Name    string `xml:"name,attr"`
			} `xml:"follow_parameter"`
		} `xml:"parameter"`
	} `xml:"group"`
	UserIndex        string `xml:"user_index,attr"`
	Name             string `xml:"name,attr"`
	Description      string `xml:"description,attr"`
	Manufacturer     string `xml:"manufacturer,attr"`
	Model            string `xml:"model,attr"`
	SerialNumber     string `xml:"serial_number,attr"`
	SoftwareVersion  string `xml:"software_version,attr"`
	HardwareVersion  string `xml:"hardware_version,attr"`
	InstallationSite string `xml:"installation_site,attr"`
	HistoryStorage   string `xml:"is_enable_history,attr"`
	index            string
}

func addImportCommands() {
	importCmd := &cobra.Command{
		Use:   "import",
		Short: "数据导入操作",
	}

	// 导入其他配置
	importConfigCmd := &cobra.Command{
		Use:   "config [配置文件路径]",
		Short: "导入平台配置",
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			ctx := getContext(cmd)
			configPath := args[0]

			if ctx.Verbose {
				fmt.Printf("正在导入配置文件: %s\n", configPath)
			}

			if err := importConfig(configPath); err != nil {
				fmt.Printf("❌ 导入失败: %v\n", err)
				return
			}

			fmt.Println("✅ 配置导入完成")
		},
	}

	// 新增模型导入命令
	importModelCmd := &cobra.Command{
		Use:   "model [模型文件路径]",
		Short: "导入模型配置（全量）",
		Long:  `从XML文件导入设备模型配置（包括设备信息、通信配置、分组参数等）`,
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			ctx := getContext(cmd)
			modelPath := args[0]

			if ctx.Verbose {
				fmt.Printf("正在导入模型文件: %s\n", modelPath)
			}

			if err := importFullWithGorm(modelPath); err != nil {
				fmt.Printf("❌ 导入失败: %v\n", err)
				return
			}

			fmt.Println("✅ 模型导入完成")
		},
	}

	// 添加命令到命令组
	importCmd.AddCommand(importConfigCmd, importModelCmd)
	RootCmd.AddCommand(importCmd)
}

func importConfig(filePath string) error {
	fmt.Printf("导入配置: %s\n", filePath)
	return nil
}

func importFullWithGorm(filePath string) error {
	// 读取并解析XML
	xmlFile, err := os.ReadFile(filePath)
	if err != nil {
		return fmt.Errorf("读取文件失败: %w", err)
	}

	var full FullImportXML
	if err := xml.Unmarshal(xmlFile, &full); err != nil {
		return fmt.Errorf("XML解析失败: %w", err)
	}

	// 获取GORM数据库实例
	db := sys.DbIns()
	if db == nil {
		return fmt.Errorf("数据库连接未初始化")
	}

	// 开启事务
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	createTime := time.Now().Unix()
	sn := 0
	full.index = full.Name

	// ===================== 1. 创建设备 =====================
	device := common.SDeviceInfo{
		SPlatObject: common.SPlatObject{
			PIndex:     full.index,
			Name:       full.Name,
			Descr:      full.Description,
			CreateTime: createTime,
			Sn:         sn,
		},
		Manufacturer:     full.Manufacturer,
		Model:            full.Model,
		SerialNumber:     full.SerialNumber,
		SoftwareVersion:  full.SoftwareVersion,
		HardwareVersion:  full.HardwareVersion,
		InstallationSite: full.InstallationSite,
		UserIndex:        full.UserIndex,
		IsEnableHistory:  common.MapEnableType(full.HistoryStorage),
	}
	sn++

	if err := tx.Create(&device).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("创建设备失败: %w", err)
	}

	// ===================== 2. 创建通信配置 =====================
	var ConfigJson string
	if full.Config.Type == "tcp" || full.Config.Type == "udp" {
		ConfigJson = fmt.Sprintf(
			`{"ip":"%s","port":%d,"timeout":%d}`,
			full.Config.IP,
			full.Config.Port,
			full.Config.Timeout,
		)
	} else if full.Config.Type == "serial" {
		ConfigJson = fmt.Sprintf(
			`{
            "port": "%s",
            "baud_rate": %d,
            "data_bits": %d,
            "stop_bits": %d,
            "parity": "%s",
            "timeout": %d
        }`,
			full.Config.SerialPort,
			full.Config.BaudRate,
			full.Config.DataBits,
			full.Config.StopBits,
			full.Config.Parity,
			full.Config.Timeout,
		)
	}

	config := common.SCommunicationConfig{
		SPlatObject: common.SPlatObject{
			PIndex:     full.Config.Name,
			Name:       full.Config.Name,
			Descr:      full.Config.Description,
			CreateTime: createTime,
			Sn:         sn,
		},
		ConfigType: full.Config.Type,
		ConfigJson: ConfigJson,
	}
	sn++

	if err := tx.Create(&config).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("创建通信配置失败: %w", err)
	}

	// ===================== 3. 创建分组和参数 =====================
	for i, group := range full.Groups {
		full.Groups[i].index = full.index + "." + group.Name
		group.index = full.index + "." + group.Name
		groupObj := common.SGroupInfo{
			SPlatObject: common.SPlatObject{
				PIndex:     group.index,
				Name:       group.Name,
				Descr:      group.Description,
				CreateTime: createTime,
				Sn:         sn,
			},
			DeviceIndex: full.index,
		}
		sn++

		if err := tx.Create(&groupObj).Error; err != nil {
			tx.Rollback()
			return fmt.Errorf("创建分组失败: %w", err)
		}

		for j, param := range group.Parameters {
			full.Groups[i].Parameters[j].index = group.index + "." + param.Name
			param.index = group.index + "." + param.Name

			paramObj := common.SArgumentInfo{
				SPlatObject: common.SPlatObject{
					PIndex:     param.index,
					Name:       param.Name,
					Descr:      param.Description,
					CreateTime: createTime,
					Sn:         sn,
				},
				GroupIndex:      group.index,
				ValueType:       common.MapDataType(param.DataType),
				ArgType:         common.MapParamType(param.ParamType),
				Value:           param.DefaultValue,
				PushType:        common.MapTriggerType(param.TriggerType),
				EnWrite:         common.EArgWriteEnabled, // 默认启用写
				PushCondition:   param.TriggerCondition,
				ByteOrder:       common.EByteOrderBigEndian,
				IsEnableHistory: common.MapEnableType(param.HistoryStorage),
			}
			sn++

			if err := tx.Create(&paramObj).Error; err != nil {
				tx.Rollback()
				return fmt.Errorf("创建参数失败: %w", err)
			}
		}
	}

	// ===================== 4. 创建协议信息 =====================
	protocol := common.SProtocolInfo{
		SPlatObject: common.SPlatObject{
			PIndex:     full.Protocol.Name,
			Name:       full.Protocol.Name,
			Descr:      full.Protocol.Description,
			CreateTime: createTime,
			Sn:         sn,
		},
		DeviceIndex: full.index,
		ConfigIndex: config.PIndex,
		Type:        common.EAcquisitionProtocolModbus,
		State:       common.MapEnableType(full.Protocol.State),
	}
	sn++

	if err := tx.Create(&protocol).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("创建协议信息失败: %w", err)
	}

	// ===================== 5. 创建Modbus点 =====================
	for _, group := range full.Groups {
		for _, param := range group.Parameters {
			if param.Point == nil {
				continue
			}
			pointObj := common.SModbusPoints{
				ProtocolIndex: protocol.PIndex,
				AgrIndex:      param.index,
				Type:          common.MapModbusType(param.Point.TypeStr),
				SlaveId:       param.Point.SlaveID,
				Address:       uint16(param.Point.Address),
				Base:          float32(param.Point.Base),
				Coef:          float32(param.Point.Coef),
				Offset:        param.Point.Offset,
				Length:        param.Point.Length,
				Interval:      param.Point.Interval,
				Priority:      param.Point.Priority,
			}

			if err := tx.Create(&pointObj).Error; err != nil {
				tx.Rollback()
				return fmt.Errorf("创建Modbus点失败(%s): %w", param.index, err)
			}
		}
	}

	// ===================== 6. 创建跟随关系 =====================
	for _, group := range full.Groups {
		for _, param := range group.Parameters {
			if len(param.FollowParameters) == 0 {
				continue
			}

			for _, follow := range param.FollowParameters {
				// 构造跟随参数索引 (可能是当前设备或其他设备)
				followIndex := follow.DevName + "." + follow.Group + "." + follow.Name
				followArg := common.FollowArg{
					PushIndex:   param.index,
					FollowIndex: followIndex,
				}

				if err := tx.Create(&followArg).Error; err != nil {
					fmt.Printf("⚠️ 警告: 创建跟随关系失败 [%s → %s]: %v\n", param.index, followIndex, err)
				}
			}
		}
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return fmt.Errorf("提交事务失败: %w", err)
	}

	// 统计信息
	totalGroups := len(full.Groups)
	totalParams := 0
	totalPoints := 0 // 实际创建的Modbus点数量
	totalFollows := 0

	for _, group := range full.Groups {
		totalParams += len(group.Parameters)

		for _, param := range group.Parameters {
			totalFollows += len(param.FollowParameters)

			// 只统计存在的点
			if param.Point != nil {
				totalPoints++
			}
		}
	}

	fmt.Printf("✅ 全量导入成功！设备: %s\n", full.Name)
	fmt.Printf("   分组: %d, 参数: %d, Modbus点: %d, 跟随关系: %d\n", totalGroups, totalParams, totalPoints, totalFollows)
	return nil
}
